#include "LSBSteg.h"
#include "BitOperation.h"
#include <random>
LSBSteg::LSBSteg()
{

}
QImage LSBSteg::lsbImbedded(QByteArray &msg)
{
    QImage ans=m_carrierIamge;
    if(msg.size()*8+32>this->m_carrierIamge.sizeInBytes()){
        return QImage();
    }
    auto data_car=ans.bits();
    int i=0;
    //存下秘密信息长度
    int len=msg.size();
    for(int k=0;k<32;++k){
        SET_BIT(data_car[i],0,len,k);
        ++i;
    }
    //存储秘密信息
    for(int k=0;k<msg.size();++k){
        for(int j=7;j>=0;--j){
            SET_BIT(data_car[i],0,msg[k],j);
            ++i;
        }
    }
    std::random_device rd;
    std::default_random_engine eng(rd());
    std::uniform_int_distribution<int> distr(0, 1);
    for(;i<m_carrierIamge.sizeInBytes();++i){
        int tem=distr(eng);
        if(tem){
            set_bit(data_car[i],0);
        }else{
            clr_bit(data_car[i],0);
        }
    }
    return ans;
}

bool LSBSteg::lsbImbedded(QImage &image, const QByteArray &msg)
{
    if(msg.size()*8+33>image.sizeInBytes()){
        return false;
    }
    auto data_car=image.bits();
    int i=0;
    int len=msg.size();
    for(int k=0;k<32;++k){
        SET_BIT(data_car[i],0,len,k);
        ++i;
    }
    for(int k=0;k<msg.size();++k){
        for(int j=7;j>=0;--j){
            SET_BIT(data_car[i],0,msg[k],j);
            ++i;
        }
    }
    std::random_device rd;
    std::default_random_engine eng(rd());
    std::uniform_int_distribution<int> distr(0, 1);
    for(;i<image.sizeInBytes();++i){
        int tem=distr(eng);
        if(tem){
            set_bit(data_car[i],0);
        }else{
            clr_bit(data_car[i],0);
        }
    }
    return true;
}

bool LSBSteg::lsbImbedded(uchar *image, int len,const QByteArray &msg)
{
    if(msg.size()*8+32>len){
        return false;
    }
    auto data_car=image;
    int i=0;
    for(int k=0;k<32;++k){
        SET_BIT(data_car[i],0,msg.size(),k);
        ++i;
    }
    for(int k=0;k<msg.size();++k){
        for(int j=7;j>=0;--j){
            SET_BIT(data_car[i],0,msg[k],j);
            ++i;
        }
    }
    std::random_device rd;
    std::default_random_engine eng(rd());
    std::uniform_int_distribution<int> distr(0, 1);
    for(;i<len;++i){
        int tem=distr(eng);
        if(tem){
            set_bit(data_car[i],0);
        }else{
            clr_bit(data_car[i],0);
        }
    }
    return true;
}

QImage LSBSteg::lsbImbedded(QImage &&image, const QByteArray &msg)
{
    if(msg.size()*8+32>image.sizeInBytes()){
        return QImage();
    }
    auto data_car=image.bits();
    int i=0;
    int len=msg.size();
    for(int k=0;k<32;++k){
        SET_BIT(data_car[i],0,len,k);
        ++i;
    }
    for(int k=0;k<len;++k){
        for(int j=7;j>=0;--j){
            SET_BIT(data_car[i],0,msg[k],j);
            ++i;
        }
    }
    std::random_device rd;
    std::default_random_engine eng(rd());
    std::uniform_int_distribution<int> distr(0, 1);
    for(;i<image.sizeInBytes();++i){
        int tem=distr(eng);
        if(tem){
            set_bit(data_car[i],0);
        }else{
            clr_bit(data_car[i],0);
        }
    }
    return image;
}

bool LSBSteg::lsbImbedded(QImage &image, uchar *msg, int len)
{
    if(len*8+32>image.sizeInBytes()){
        return false;
    }
    auto data_car = image.bits();
    int i=0;
    for(int k=0;k<32;++k){
        SET_BIT(data_car[i],0,len,k);
        ++i;
    }
    for(int k=0;k<len;++k){
        for(int j=7;j>=0;--j){
            SET_BIT(data_car[i],0,msg[k],j);
            ++i;
        }
    }
    std::random_device rd;
    std::default_random_engine eng(rd());
    std::uniform_int_distribution<int> distr(0, 1);
    for(;i<image.sizeInBytes();++i){
        int tem=distr(eng);
        if(tem){
            set_bit(data_car[i],0);
        }else{
            clr_bit(data_car[i],0);
        }
    }
    return true;
}

QImage LSBSteg::lsbImbedded(QImage &&image, uchar *msg, int len)
{
    if(len*8+32>image.sizeInBytes()){
        return QImage();
    }
    auto data_car = image.bits();
    int i=0;
    for(;i<32;++i){
        SET_BIT(data_car[i],0,len,i);
    }
    for(int k=0;k<len;++k){
        for(int j=7;j>=0;--j){
            SET_BIT(data_car[i],0,msg[k],j);
            ++i;
        }
    }
    std::random_device rd;
    std::default_random_engine eng(rd());
    std::uniform_int_distribution<int> distr(0, 1);
    for(;i<image.sizeInBytes();++i){
        int tem=distr(eng);
        if(tem){
            set_bit(data_car[i],0);
        }else{
            clr_bit(data_car[i],0);
        }
    }
    return image;
}

QByteArray LSBSteg::lsbRetrieval(const uchar *msg,int len_msg)
{
    int len=0;
    auto data_car=msg;
    int i=0;
    for(;i<32;++i){
        SET_BIT(len,i,data_car[i],0);
    }
    if(len==0||len_msg-32<len){
        return QByteArray();
    }
    QByteArray ans{len,'0'};
    for(int j=0;j<len;++j){
        for(int k=7;k>=0;--k){
            SET_BIT(ans[j],k,data_car[i],0);
            ++i;
        }
    }
    return ans;
}
